home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1999 January: Mac OS SDK / Dev.CD Jan 99 SDK1.toast / Development Kits / Apple Color OneScanner SDK / Scan Image 1.0 / scanner.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-08-24  |  13.7 KB  |  559 lines  |  [TEXT/CWIE]

  1. /*************************************************************************************
  2. #
  3. #        scanner.c
  4. #
  5. #        This segment handles scanner calls.
  6. #
  7. #        Author(s):     Michael Marinkovich
  8. #                    Apple Developer Technical Support
  9. #                    marink@apple.com
  10. #
  11. #        Modification History: 
  12. #
  13. #            2/10/96        MWM     Initial coding                     
  14. #
  15. #        Copyright © 1992-96 Apple Computer, Inc., All Rights Reserved
  16. #
  17. #
  18. #        You may incorporate this sample code into your applications without
  19. #        restriction, though the sample code has been provided "AS IS" and the
  20. #        responsibility for its operation is 100% yours.  However, what you are
  21. #        not permitted to do is to redistribute the source as "DSC Sample Code"
  22. #        after having made changes. If you're going to re-distribute the source,
  23. #        we require that you make it clear in the source that the code was
  24. #        descended from Apple Sample Code, but that you've made changes.
  25. #
  26. *************************************************************************************/
  27.  
  28. #include <Controls.h>
  29. #include <Events.h>
  30. #include <ToolUtils.h>
  31. #include <Gestalt.h>
  32. #include <OSUtils.h>
  33. #include <Palettes.h>
  34.  
  35. #include "App.h"
  36. #include "Proto.h"
  37.  
  38.  
  39. //----------------------------------------------------------------------
  40. //
  41. //    DoNewScan - main entry point for scanning
  42. //                 
  43. //
  44. //----------------------------------------------------------------------
  45.  
  46. OSErr DoNewScan(CGrafPtr *dstPort)
  47. {
  48.     OSErr                err = noErr;
  49.     ScStdFeaturesRec     scannerInfo;
  50.     ScResPtr            lineArtRes;
  51.     ScResPtr            halfToneRes;
  52.     ScResPtr            grayScaleRes;
  53.     ScResPtr            biLevelColorRes;
  54.     ScResPtr            fullColorRes;
  55.     ScHalfTonePtr        halfToneNames;
  56.     CTabHandle            cTab = nil;
  57.     UserSettings        userSettings;
  58.     Rect                scanRect;
  59.     UInt32                pixelDepth;
  60.     Fixed                height;
  61.     Fixed                width;
  62.     
  63.     if (dstPort != nil)
  64.     {
  65.         // get supported resolutions and halftone names from scanner.
  66.         err = GetScannerInfo(&scannerInfo, &lineArtRes,
  67.                              &halfToneRes, &grayScaleRes,
  68.                               &biLevelColorRes, &fullColorRes, 
  69.                              &halfToneNames);
  70.          
  71.         if (err == noErr)
  72.         {
  73.             // call our user input dialog function which will return 
  74.             // the users choices in the userSettings parameter. I defined 
  75.             // the userSettings struct for portability of the information.
  76.             err = GetUserScanInfo(dstPort, &scannerInfo,
  77.                                   lineArtRes, halfToneRes, grayScaleRes,
  78.                                     biLevelColorRes, fullColorRes, 
  79.                                   halfToneNames, &userSettings);
  80.                                   
  81.             if (err == noErr)
  82.             {    
  83.                 SetCursor(*GetCursor(watchCursor));
  84.                 
  85.                 // calculate height & width w/ fixmath for accuracy
  86.                 height = (FixDiv(FixMul(userSettings.height, FixDiv(userSettings.resolution, 72L)),
  87.                           scannerInfo.scanLengthDen) >> 16) * scannerInfo.scanLengthDen;
  88.                 width = (FixDiv(FixMul(userSettings.width, FixDiv(userSettings.resolution, 72L)),
  89.                           scannerInfo.scanWidthDen) >> 16) * scannerInfo.scanWidthDen;
  90.                 
  91.  
  92.                 SetRect(&scanRect, 0, 0, width, height);
  93.     
  94.                 pixelDepth = scannerInfo.composition[userSettings.compMode].bitsPerPixel;
  95.                 
  96.                 // we need to go through the hoops and find the actual pixel size
  97.                 if (pixelDepth > 8)
  98.                 {
  99.                     switch (pixelDepth)
  100.                     {
  101.                         case 0x800000:
  102.                             pixelDepth = 32;
  103.                             break;
  104.                         
  105.                         case 0x4000:
  106.                             pixelDepth = 16;
  107.                             break;
  108.                         
  109.                         case 0x88:
  110.                             pixelDepth = 8;
  111.                             break;
  112.                     }
  113.                                     
  114.                 }
  115.                 
  116.                 userSettings.pixelDepth = pixelDepth;
  117.                 
  118.                 // if compmode is grayscale then we want a gray clut for our
  119.                 // offscreen. The System contains handy gray clut resources.
  120.                 if (userSettings.compMode == 2)
  121.                     cTab = GetCTable(40);
  122.                     
  123.                 err = NewGWorld(dstPort, pixelDepth, &scanRect, cTab, nil, nil);
  124.                 
  125.                 if (err == noErr && *dstPort != nil)
  126.                 {                    
  127.                     err = DoScan(*dstPort, scannerInfo, &userSettings, scanRect);
  128.                 }
  129.  
  130.                 SetCursor(&qd.arrow);
  131.  
  132.             }
  133.                 
  134.         }
  135.                         
  136.     }
  137.     else
  138.         err = paramErr;
  139.         
  140.             
  141.     return err;
  142. }
  143.  
  144.     
  145. //----------------------------------------------------------------------
  146. //
  147. //    DoScan - open connection to scanner, setup scanParams and call
  148. //             scan function.
  149. //
  150. //----------------------------------------------------------------------
  151.  
  152. OSErr DoScan(CGrafPtr dstPort, ScStdFeaturesRec scannerInfo,
  153.              UserSettingsPtr userSettings, Rect scanRect)
  154. {
  155.     OSErr                err = noErr;
  156.     short                scanRef;
  157.     short                ADFStatus;
  158.     ScScanAreaRec        scanParams;
  159.                  
  160.     scanRef = 0;
  161.  
  162.     err = ScOpen(&scanRef);
  163.     
  164.     if (err == noErr)
  165.     {
  166.         err = SetupScan(scanRef, scannerInfo, userSettings, scanRect, &scanParams);
  167.         
  168.         // if ADF is specified then check the status 
  169.         if (userSettings->inputMethod == kSourceADFItem)
  170.         {
  171.             err = ScVendorUnique(scanRef, scUniqueGetADFStatus, (char *)&ADFStatus);
  172.             if (err == noErr)
  173.             {
  174.                 // bit 3 ADF cover open
  175.                 if (ADFStatus & 0x08)
  176.                     err = kADFCoverOpenErr;
  177.                 
  178.                 // bit 2 ADF Paper Jam
  179.                 if (ADFStatus & 0x04)
  180.                     err = kADFPaperJamErr;
  181.                 
  182.                 // bit 1 ADF No Paper
  183.                 if (ADFStatus & 0x02)
  184.                     err = kADFNoPaperErr;
  185.                     
  186.             }        
  187.         }
  188.         
  189.         if (err == noErr)
  190.         {
  191.             err = ScanImage(scanRef, dstPort, scannerInfo, scanParams.scanAreas[0]);
  192.         }
  193.     }
  194.     
  195.     if (scanRef != nil)
  196.         (void)ScClose(scanRef);    
  197.     
  198.     return err;
  199.  
  200. }
  201.  
  202.  
  203. //----------------------------------------------------------------------
  204. //
  205. //    GetInputMethods - Determine if a auto document feeder or transparency
  206. //                       unit is connected. If either is connected the info
  207. //                      will be returned in TPUADFInfo.
  208. //----------------------------------------------------------------------
  209.  
  210. OSErr GetInputMethods(Boolean *ADF, Boolean *TPU, ScTPUADFInfoPtr TPUADFInfo)
  211. {
  212.     OSErr                err;
  213.     short                scanRef;
  214.     short                adfStatus;
  215.     short                tpuStatus;
  216.     char                 *paramPtr;
  217.     
  218.     scanRef = 0;
  219.  
  220.     err = ScOpen(&scanRef);
  221.     
  222.     if (err == noErr)
  223.     {
  224.         err = ScVendorUnique(scanRef, scUniqueGetADFStatus, (char *)&adfStatus);
  225.         err = ScVendorUnique(scanRef, scUniqueGetTPUStatus, (char *)&tpuStatus);
  226.         if (err == noErr)
  227.         {
  228.             // bit 0 - 1 = ADF Not Present
  229.             *ADF = !(adfStatus & 1);
  230.             
  231.             // boolean returned for TPU status
  232.             *TPU = tpuStatus;
  233.             
  234.             err = ScVendorUnique(scanRef, scUniqueGetTPUADFInfo, (char *)TPUADFInfo);
  235.  
  236.         }    
  237.  
  238.     }
  239.  
  240.     if (scanRef != nil)
  241.         (void)ScClose(scanRef);    
  242.     
  243.     return err;
  244.  
  245. }
  246.  
  247.  
  248. //----------------------------------------------------------------------
  249. //
  250. //    GetScannerInfo - get supported resolutions for each mode and get
  251. //                     list of halftone name.
  252. //
  253. //----------------------------------------------------------------------
  254.  
  255. OSErr GetScannerInfo(ScStdFeaturesRec *scannerInfo, ScResPtr *lineArtRes,
  256.                      ScResPtr *halfToneRes, ScResPtr *grayScaleRes,
  257.                      ScResPtr *biLevelColorRes, ScResPtr *fullColorRes, 
  258.                      ScHalfTonePtr *halfToneNames)
  259. {
  260.     OSErr            err = noErr;
  261.     ScResPtr        resList;
  262.     short            scanRef;
  263.     short            compMode;
  264.     short            numElements;             
  265.  
  266.  
  267.     scanRef = 0;
  268.     
  269.     err = ScOpen(&scanRef);
  270.     
  271.     if (err == noErr)
  272.     {
  273.         err = ScGetStdFeatures(scanRef, scannerInfo,
  274.                                  sizeof(ScStdFeaturesRec));
  275.  
  276.         if (err == noErr)
  277.         {
  278.             for (compMode = scLineArt; compMode <= scFullColor; compMode++)
  279.             {
  280.                 if (scannerInfo->composition[compMode].resElements != 0)
  281.                 {
  282.                     numElements = scannerInfo->composition[compMode].resElements;
  283.                     resList = (ScResPtr)NewPtr(numElements * sizeof(short));
  284.                     
  285.                     if (resList != nil)
  286.                     {                        
  287.                         err = ScGetRes(scanRef, compMode, resList);
  288.                         if (err == noErr)
  289.                         {                        
  290.                             switch (compMode)
  291.                             {
  292.                                 case scLineArt:
  293.                                     if (lineArtRes != nil)
  294.                                         *lineArtRes = resList;
  295.                                     break;
  296.                                     
  297.                                 case scHalfTone:
  298.                                     if (halfToneRes != nil)
  299.                                         *halfToneRes = resList;
  300.                                     break;
  301.                                     
  302.                                 case scGrayScale:
  303.                                     if (grayScaleRes != nil)
  304.                                         *grayScaleRes = resList;
  305.                                     break;
  306.                                 
  307.                                 case scBiLevelColor:
  308.                                     if (biLevelColorRes != nil)
  309.                                         *biLevelColorRes = resList;
  310.                                     break;
  311.                                     
  312.                                 case scFullColor:
  313.                                     if (fullColorRes != nil)
  314.                                         *fullColorRes = resList;
  315.                                     break;
  316.                                 
  317.                                 default:
  318.                                     break;
  319.                             }
  320.                         }    
  321.                     }
  322.                 }
  323.             }
  324.         }
  325.         
  326.         if (scannerInfo->composition[scHalfTone].resElements != 0 && halfToneNames != nil)
  327.         {
  328.             numElements = scannerInfo->composition[scHalfTone].halfToneElements;
  329.             
  330.             *halfToneNames = (ScHalfTonePtr)NewPtr(numElements * sizeof(Str31));
  331.             
  332.             if (*halfToneNames == nil)
  333.                 HandleError(MemError(), false);
  334.                 
  335.             err = ScGetHalfTones(scanRef, scHalfTone, *halfToneNames);
  336.  
  337.         }
  338.         
  339.         if (scanRef != nil)
  340.             err = ScClose(scanRef);
  341.  
  342.     }
  343.     
  344.     return err;
  345.  
  346. }
  347.  
  348.  
  349. //----------------------------------------------------------------------
  350. //
  351. //    SetupScan - tell the scanner where and how the scan should take place
  352. //                    
  353. //
  354. //----------------------------------------------------------------------
  355.  
  356. OSErr SetupScan(short scanRef, ScStdFeaturesRec scannerInfo,
  357.                 UserSettingsPtr userSettings, Rect scanRect, 
  358.                 ScScanAreaRec *scanInfo)
  359. {
  360.     OSErr        err;
  361.     UInt32        pixelDepth;
  362.     short        uniqueCode;
  363.     
  364.     // tell scanner which input method we want...FlatBed, ADF, or TPU
  365.     switch (userSettings->inputMethod)
  366.     {
  367.         case kSourceFlatbedItem:
  368.             uniqueCode = 3;
  369.             err = ScVendorUnique(scanRef, scUniqueSetADFPriority, (char *)&uniqueCode);
  370.             break;
  371.         
  372.         case kSourceADFItem:
  373.             uniqueCode = 1;
  374.             err = ScVendorUnique(scanRef, scUniqueSetADFPriority, (char *)&uniqueCode);
  375.             break;
  376.         
  377.         case kSourceTPUItem:
  378.             uniqueCode = 3;
  379.             err = ScVendorUnique(scanRef, scUniqueSetADFPriority, (char *)&uniqueCode);
  380.             break;
  381.         
  382.         default:
  383.             err = paramErr;
  384.             break;
  385.             
  386.     }
  387.     
  388.  
  389.     // change the input method from our popup values to the actual input methods.
  390.     if (err == noErr)
  391.     {
  392.         err = ScVendorUnique(scanRef, scUniqueSetTPUMode, (char *)&userSettings->TPULight);
  393.         if (err == noErr)
  394.         {
  395.             err = ScVendorUnique(scanRef, scUniqueSetTPUNP, (char *)&userSettings->TPUFilm);
  396.             if (err == noErr)
  397.             {
  398.                 uniqueCode = userSettings->TPUVendor;
  399.                 err = ScVendorUnique(scanRef, scUniqueSetTPUFilmType, (char *)&uniqueCode);
  400.             }
  401.         }
  402.     }
  403.  
  404.     if (scannerInfo.composition[userSettings->compMode].brightnessRange != 0)
  405.         userSettings->brightness |= 0x8000;
  406.         
  407.     if (scannerInfo.composition[userSettings->compMode].contrastRange != 0)
  408.         userSettings->contrast |= 0x8000;
  409.     
  410.     pixelDepth = userSettings->pixelDepth;
  411.     
  412.     // recognizes 24 bit not 32
  413.     if (pixelDepth == 32) 
  414.         pixelDepth = 24;
  415.     
  416.     scanInfo->reserved = 0;
  417.     scanInfo->numAreas = 1;
  418.  
  419.     scanInfo->scanAreas[0].reserved        = 0;
  420.     scanInfo->scanAreas[0].xDpi            = userSettings->resolution;
  421.     scanInfo->scanAreas[0].yDpi            = userSettings->resolution;
  422.     scanInfo->scanAreas[0].scanRect        = scanRect;
  423.     scanInfo->scanAreas[0].brightness    = userSettings->brightness;
  424.     scanInfo->scanAreas[0].contrast        = userSettings->contrast;
  425.     scanInfo->scanAreas[0].composition    = userSettings->compMode;
  426.     scanInfo->scanAreas[0].bitsPerPixel    = pixelDepth;
  427.     scanInfo->scanAreas[0].halfTone        = userSettings->ditherPattern;
  428.  
  429.     err = ScSetScanArea(scanRef, scanInfo);
  430.     
  431.     return err;
  432.  
  433. }
  434.  
  435.     
  436. //----------------------------------------------------------------------
  437. //
  438. //    ScanGWorldImage - scan into supplied grafPtr
  439. //                    
  440. //
  441. //----------------------------------------------------------------------
  442.  
  443. OSErr ScanImage(short scanRef, CGrafPtr dstPort,
  444.                 ScStdFeaturesRec scannerInfo, ScAreaRec scanParams)
  445. {
  446.     OSErr            err;
  447.     PixMapHandle    thePix;
  448.     Ptr                destImage;
  449.     Ptr                buffer = nil;
  450.     Ptr                rovingBuffer;
  451.     Ptr                destBuffer;
  452.     Rect            scanRect;
  453.     long            count;
  454.     long            dataLen;
  455.     long            minDataLen;
  456.     short            byteWidth;
  457.     short            minReadSize;
  458.     short            numScannedRows;
  459.     short            destRowBytes;
  460.     short            bitsPerPixel;
  461.     short            rowNum;
  462.     short            channel;
  463.     short            index;
  464.     
  465.     thePix = GetGWorldPixMap(dstPort);
  466.     if (LockPixels(thePix))
  467.     {
  468.         SetGWorld(dstPort, nil);
  469.         EraseRect(&dstPort->portRect);
  470.         
  471.         destImage = GetPixBaseAddr(thePix);
  472.         destRowBytes = (**thePix).rowBytes & 0x3FFF;
  473.         
  474.         scanRect = dstPort->portRect;
  475.         bitsPerPixel = scanParams.bitsPerPixel;
  476.  
  477.         if (scanParams.composition == scFullColor)
  478.             byteWidth = ((((8 * (scanRect.right - 1)) / 8) + 1) - 
  479.                                 ((8 * scanRect.left) / 8)) * 3;
  480.         else
  481.             byteWidth = (((bitsPerPixel * (scanRect.right - 1)) / 8) + 1) -
  482.                         ((bitsPerPixel * scanRect.left) / 8);
  483.         
  484.         minReadSize = scannerInfo.composition[scanParams.composition].minReadSize;
  485.         
  486.         if (minReadSize > byteWidth)
  487.             minDataLen = byteWidth * ((minReadSize - 1) / byteWidth + 1);
  488.         else
  489.             minDataLen = byteWidth;
  490.             
  491.         // If scanning 24-bit color, allocate a buffer to rearrange pixel data
  492.         if (scanParams.composition == scFullColor)
  493.             buffer = NewPtrClear(minDataLen + byteWidth * 2);
  494.         
  495.         err = MemError();
  496.         
  497.         // Loop until the scan is done
  498.         while (err == noErr)
  499.         {
  500.             // Set maximum amount of data to read at minDataLen
  501.             dataLen = minDataLen;
  502.             
  503.             if (err == noErr && dataLen > 0)
  504.             {
  505.                 if (scanParams.composition == scFullColor)
  506.                 {
  507.                     // Scan a piece of the image
  508.                     err = ScDoScan(scanRef, buffer, &dataLen, 0, 0, 0);
  509.                     
  510.                     numScannedRows = dataLen / byteWidth;
  511.                     rowNum = 1;
  512.                     rovingBuffer = buffer;
  513.                     
  514.                     while (rowNum <= numScannedRows)
  515.                     {
  516.                         for (channel = 1; channel <= 3; channel++)
  517.                         {
  518.                             for (index = 0; index < (byteWidth / 3) - 1; index++)
  519.                             {
  520.                                 // Convert image to Color QuickDraw format
  521.                                 destBuffer = (Ptr)((long)destImage + channel + index * 4);
  522.                                 *destBuffer = *(Ptr)((long)rovingBuffer + index + 
  523.                                                     (byteWidth / 3) * (channel - 1));
  524.                             }
  525.                         }
  526.                         
  527.                         destImage = (Ptr)((long)destImage + destRowBytes);
  528.                         rovingBuffer = (Ptr)((long)rovingBuffer + byteWidth);
  529.  
  530.                         rowNum++;
  531.                     }
  532.                 }
  533.                 else
  534.                 {
  535.                     // Scan a piece of the image
  536.                     err = ScDoScan(scanRef, destImage, &dataLen, 0, byteWidth, destRowBytes);
  537.                     // If continuing scan, reposition destImage for more
  538.                     destImage = (Ptr)((long)destImage + (dataLen / byteWidth) * destRowBytes);
  539.                 }
  540.                 
  541.             }
  542.             
  543.         }
  544.         
  545.         // If error was scEOS (end of scan), then everything is OK
  546.         if (err == scEOS)
  547.             err = noErr;
  548.             
  549.         // Get rid of the buffer used for 24-bit color
  550.         if (buffer != nil)
  551.             DisposePtr(buffer);
  552.             
  553.         UnlockPixels(thePix);
  554.     }
  555.     
  556.     
  557.     return err;
  558.  
  559. }